import axios from 'axios'
import store from '@/store'
import router from '@/router'
import { Notify } from 'vant'

/*
  过滤重复请求！
*/
const pendings = []
const CancelToken = axios.CancelToken
// 移除重复请求（如果组件在离开页面时需要清除当前axios请求，则可以调用此函数！！！）
export function removePending(config) {
  const { url, method = 'get', params = '{}' } = config
  const i = pendings.findIndex(v => v.url === url && v.method === method && v.params === params)
  if (i > -1) {
    pendings[i].cancel('操作太频繁，请稍后再试')
    pendings.splice(i, 1)
  }
}

export default class Request {
  instance = null // axios实例
  // 默认的url从环境变量中获取
  constructor(config) {
    this.instance = axios.create(config)
    this.instance.defaults.headers.post['Content-Type'] = 'application/json' // 设置post请求头
    this.requestFn()
    this.responseFn()
  }

  // 请求拦截器
  requestFn() {
    this.instance.interceptors.request.use(
      config => {
        // 过滤重复请求
        console.log('-- 请求的config --', config)
        removePending({ url: config.url, method: config.method, params: ['get', 'delete'].includes(config.method) ? JSON.stringify(config.params) : config.data })
        config.cancelToken = new CancelToken(c =>
          pendings.push({ url: config.url, method: config.method, params: ['get', 'delete'].includes(config.method) ? JSON.stringify(config.params) : config.data, cancel: c })
        )
        if (config.method === 'get') {
          config.data = true // 这个是关键点，加入这行就可以了  解决get  请求添加不上content_type
        }
        // 设置token
        const token = store.user.token
        token && (config.headers.token = token)
        return config
      },
      err => {
        Notify({ message: '请求错误', color: '#ad0000', background: '#ffe1e1' })
        return Promise.reject(err)
      }
    )
  }

  // 响应拦截器
  responseFn() {
    this.instance.interceptors.response.use(
      res => {
        removePending({ url: res.config.url, method: res.config.method, params: ['get', 'delete'].includes(res.config.method) ? JSON.stringify(res.config.params) : res.config.data })
        if (res.status === 200) {
          if (res.headers.token) {
            store.user.SET_TOKEN(res.headers.token)
          }
          return Promise.resolve(res.data)
        }
        Notify({ message: res.message, color: '#ad0000', background: '#ffe1e1' })
      },
      err => {
        return errHandle(err)
      }
    )
  }

  // 注意：如果需要下载excel等文件流，config需要配置 { responseType: 'blob' }
  get(url, params = {}, config = {}) {
    return this.instance.get(url, { params: params, ...config })
  }

  delete(url, params = {}, config = {}) {
    return this.instance.delete(url, { params: params, ...config })
  }

  post(url, data = {}, config = {}) {
    return this.instance.post(url, data, config)
  }

  put(url, data = {}, config = {}) {
    return this.instance.put(url, data, config)
  }

  all(requestArr) {
    return axios.all(requestArr)
  }
}

// 状态码错误的处理函数
function errHandle(err) {
  const { response } = err
  // 当服务器返回错误码时
  if (response) {
    switch (response.status) {
      case 400:
        Notify({ message: response.data.message, color: '#ad0000', background: '#ffe1e1' })
        break
      case 401:
        // 用户信息已变更 / 登录过期'
        Notify({ message: response.data.message, color: '#ad0000', background: '#ffe1e1' })
        store.user.SET_TOKEN('')
        store.user.SET_USERINFO({})
        sessionStorage.setItem('user', '')
        sessionStorage.setItem('keepAlive', [])
        location.reload()
        setTimeout(() => {
          router.replace('/login')
        }, 200)
        break
      case 403:
        // 拒绝访问
        Notify({ message: response.data.message, color: '#ad0000', background: '#ffe1e1' })
        break
      case 404:
        // 请求错误，未找到该资源
        Notify({ message: response.data.message, color: '#ad0000', background: '#ffe1e1' })
        break
      case 405:
        // 请求方法未允许
        Notify({ message: response.data.message, color: '#ad0000', background: '#ffe1e1' })
        break
      case 408:
        // 请求超时
        Notify({ message: response.data.message, color: '#ad0000', background: '#ffe1e1' })
        break
      case 500:
        // 服务器错误
        Notify({ message: response.data.message, color: '#ad0000', background: '#ffe1e1' })
        break
      case 503:
        // 服务器暂时无法使用
        Notify({ message: response.data.message, color: '#ad0000', background: '#ffe1e1' })
        break
      default:
        // 请求数据失败
        Notify({ message: response.data.message, color: '#ad0000', background: '#ffe1e1' })
    }
    return Promise.reject(response.data)
  } else {
    // 当服务器没有返回结果时，可能是没有网(如果断网了：可以跳转到断网页面)
    if (!window.navigator.onLine) {
      Notify({ message: '请检查网络是否连接正常', color: '#ad0000', background: '#ffe1e1' })
      return
    }
    return Promise.reject(err)
  }
}
